exports.jsonPath = {
	childrenToken : 'children',
	// 输入 JSON，要求 Array， 不能 对象
	jsonArr : null,

	/**
     * @return {Array}
     */
    toList : function(){
    	if(!this.jsonArr)throw '未输入 JSON 数据！';

        var result = [];
        array_Iterator.Fn = function(e, arr, i, j){
            result.push(e);
        }
        array_Iterator.childrenToken = this.childrenToken;
        array_Iterator(this.jsonArr, result);

        return result;
    },

    /**
     * 获取第 N 级的数据，从 0 开始。
     * @return {Object}
     */
    levelAt : function(level){
    	if(!this.jsonArr)throw '未输入 JSON 数据！';

        var result = [];
        array_Iterator.Fn = function(e, arr, i, j){
            if(j == level){
                // assert every node has a key name called "id"
                if(!this.fullPath)this.fullPath = ''; // 执行此步的时候为根目录
                e.fullPath = this.fullPath + '/' + e.id;
                result.push(e);
            }
        }
        array_Iterator.childrenToken = this.childrenToken;
        array_Iterator(this.jsonArr, result);

        return result;
    },

    /**
     * getHashValueByFullKey
     * @param   {Boolean} isAllMatch
     * @param   {String|Array}
     * @return  {Object}
     */
    hashSearch : function(path){
    	if(!this.jsonArr)throw '未输入 JSON 数据！';

        if(!path)
            throw '未输入参数！';
        else if(arguments.length > 1)     // 可变参数的条件
            path = Array.prototype.slice.call(arguments, 0);
        else if(typeof path == 'string'){  // 送入字符串的条件
            path = path.split('/');
            path.shift();
        }else if(path.pop){                 // 送入数组的条件
            // do nothing...
        }

        var result = [], i = 0, withPathData = buildPath.call(this);

        /**
         * @param {String} key
         */
        (function(key){
            var _shift = this[key];
            if(!_shift)return;
            
            result.push(_shift);
            arguments.callee.call(_shift, path[++i]);// 相当于 i++;var nextKey = path[i];arguments.callee.call(_shift, nextKey);
        }).call(withPathData, path[i]);
        
        return result;
    },

    getNode : function(path){
        var node = this.hashSearch.apply(this, arguments);
        return node.pop ? node.pop() : null;
    },  

    /**
     *  可编织任意的数据，如：      
        var h = {};
        var foo = this.webStructure.buildIndex(null, null, function(e, arr, i, j){
            if(j == 1){
                h[e.id] = e;
            }
        });
     * @param {Array} arr
     * @param {String} keyName 注意不是什么类型的数据都可以作为key！
     * @param {Function} handler
     * @return {Object}
     */
    buildIndex : function(arr, keyName, handler){
        var hash;
        
        hash    = {}
        arr     = arr       || this.tree
        keyName = keyName   || 'id';  // assert every node has a key name called "id"
        
        array_Iterator.Fn = handler;
        
        array_Iterator(arr, hash);
        
        return hash;
    }  
};

var undefinedStr = 'undefined';

/**
 * iterator
 * @param {Array} arr
 * @param {Object} scope 充分利用 JS 独有的 this 对象指针以确定函数作用域，收窄对象范围。
 * @param {Number} i
 * @param {Number} j A ghost value, 穿梭于
 */
function array_Iterator(arr, scope, i, j){
    if(typeof scope == undefinedStr)scope = this;
    if(typeof i == undefinedStr)i = 0;
    if(typeof j == undefinedStr)j = 0;

    var element = arr[i], 
    /*	该函数为递归函数，以上参数随递归变化而不同，而下面
    	此部分的参数相对“静态”，故透过 arg.callee 获取引用 */
    	selfFn = arguments.callee;

    if(typeof element == undefinedStr)return;

    // do something...
    if(selfFn.Fn && selfFn.Fn.call(scope, element, arr, i, j) == false)return;
    // do something-End
    
    var children = element[selfFn.childrenToken];
    if (children && children.length){
        // -->y
        selfFn(children, element/*已经变了这个Scope*/, 0, j + 1);// var x = j + 1; // 每一次循环children都会对j产生变化
    };
    // -->x
    selfFn(arr, scope, ++i, j /* Do not give a "j" here, cause it's needed to have j reset!*/);    
}

// 除了构建路径 path 外，还会把子元素附加到父元素身上，以为 hash 查找之用
function buildPath(){
    var hash = {};
    array_Iterator.Fn = function(e, arr, i, j){
        if(!this.fullPath)this.fullPath = '';	// 执行此步的时候为根目录
        e.fullPath = this.fullPath + '/' + e.id;// 包含父路径的全称路径
        e.sj = j; 								// 缩进
        this[e.id] = e;							// 当前结构是，直接附加在对象身上。考虑分配一个专用的 key，或者 搜索 children？
    }
     
    array_Iterator.childrenToken = this.childrenToken;
    array_Iterator(this.jsonArr, hash);
    
    return hash;
}